#include "hi_io.h" //==hi_io_set_func()、hi_io_set_pull()
#include "hi_gpio.h"
#include "hi_adc.h"
#include "hi_i2c.h"
#include "wifiiot_i2c.h"
#include "wifiiot_i2c_ex.h"
#include "wifiiot_gpio.h"
#include "wifiiot_gpio_ex.h"

#include "mq2_mqtt.h"

#include <stddef.h>
#include <unistd.h>
#include "stdlib.h"
#include "stdio.h"
#include <math.h>
#include <string.h>
#include <unistd.h>
#include "cmsis_os2.h"

#define RL 1	   // RL阻值
#define CAL_PPM 20 //校准环境中PPM值
static float R0;   //元件在洁净空气中的阻值
typedef struct
{
	float    Humidity;        //湿度
	float    Temperature;     //温度
} Temp_Humi;

void SensorInit(void)
{
     
	printf("MQ2 init \n");
	MQ2_PPM_Calibration(); //校准mq2
	printf("AGT20 init \n");
	AHT20_I2C_Init();
}

//读取touch sensor电压值
float GetVoltage(void)
{
	unsigned short data;
	if (hi_adc_read(HI_ADC_CHANNEL_6, &data, HI_ADC_EQU_MODEL_8, HI_ADC_CUR_BAIS_DEFAULT, 0) != 0)
	{
		printf("ADC6 FAILD\n");
	}
	printf("ADC6 %d \n", data);
	return (float)data * 1.8 * 4 / 4096.0;
}

/***************************************************************
 * 函数名称: GetMQ2PPM
 * 说    明: 获取PPM函数
 * 参    数: ppm 烟雾浓度
 * 返 回 值: 0 成功; -1 失败
 ***************************************************************/
float Get_MQ2_PPM(void)
{
	float voltage, RS, ppm;

	voltage = GetVoltage();
	RS = (5 - voltage) / voltage * RL;	  //计算RS
	ppm = 613.9f * pow(RS / R0, -2.074f); //计算ppm
	return ppm;
}

/***************************************************************
 * 函数名称: MQ2PPMCalibration
 * 说    明: 传感器校准函数
 * 参    数: 无
 * 返 回 值: 无
 ***************************************************************/
void MQ2_PPM_Calibration(void)
{
	float voltage = GetVoltage();
	float RS = (5 - voltage) / voltage * RL;
	R0 = RS / pow(CAL_PPM / 613.9f, 1 / -2.074f);
}


//使能i2c-1
void AHT20_I2C_Init(void)
{
    GpioInit();
    hi_io_set_func(AHT20_SDA,HI_IO_FUNC_GPIO_0_I2C1_SDA);
    GpioInit();
    hi_io_set_func(AHT20_SCL,HI_IO_FUNC_GPIO_1_I2C1_SCL);
    hi_i2c_init(AHT20_I2C_IDX,AHT20_I2C_BAUDRATE); 

	// IoSetFunc(WIFI_IOT_IO_NAME_GPIO_0, WIFI_IOT_IO_FUNC_GPIO_0_I2C1_SDA);   // GPIO_0复用为I2C1_SDA
    // IoSetFunc(WIFI_IOT_IO_NAME_GPIO_1, WIFI_IOT_IO_FUNC_GPIO_1_I2C1_SCL);   // GPIO_1复用为I2C1_SCL
    // I2cInit(WIFI_IOT_I2C_IDX_1, 400000); /* baudrate: 400kbps */
    // I2cSetBaudrate(WIFI_IOT_I2C_IDX_1, 400000);
}

static uint32_t AHT20_Read(uint8_t data[], uint32_t dataLen)
{
  hi_i2c_idx id = AHT20_I2C_IDX;
  hi_i2c_data i2cData;
  i2cData.receive_buf = data;
  i2cData.receive_len = dataLen;
  i2cData.send_buf = NULL;
  i2cData.send_len = 0;
  uint32_t result;
  result = hi_i2c_read((hi_i2c_idx)id,AHT20_READ,&i2cData);
  if(result != IOT_SUCCESS){
    printf("AHT20_Read() Failed ,%0X\n",result);
    return result; }
  return IOT_SUCCESS ;
}

static uint32_t AHT20_Write(uint8_t data[], uint32_t dataLen)
{
  hi_i2c_idx id = AHT20_I2C_IDX;
  hi_i2c_data i2cData;
  i2cData.receive_buf = NULL;
  i2cData.receive_len = 0;
  i2cData.send_buf = data;
  i2cData.send_len = dataLen;
  uint32_t result;
  result = hi_i2c_write((hi_i2c_idx)id,AHT20_WRITE,&i2cData);
  if(result != IOT_SUCCESS){
    printf("AHT20_Write() Failed ,%0X\n",result);
    return result; }
  return IOT_SUCCESS ;
}

//获取状态
static uint32_t AHT20_Status(void)
{
  uint8_t statuscmd[]={AHT20_STATUS};
  return AHT20_Read(statuscmd,sizeof(statuscmd));
}
//软复位
static uint32_t AHT20_Reset(void)
{
  uint8_t reset = {AHT20_RESET_CMD};
  return AHT20_Write(&reset,sizeof(reset));
}
//校准
static uint32_t AHT20_Initcmd(void)
{
  uint8_t initialcmd[] ={AHT20_INIT_CMD, AHT20_INIT_CMD_B1,AHT20_INIT_CMD_B2};
  return AHT20_Write(initialcmd,sizeof(initialcmd));
}
//触发测量
uint32_t AHT20_StartMeasure(void)
{
  uint8_t startcmd[] ={AHT20_TRAG_CMD, AHT20_TRAG_CMD_B1,AHT20_TRAG_CMD_B2};
  return AHT20_Write(startcmd,sizeof(startcmd));  
}

// 读取温湿度值之前， 首先要看状态字的校准使能位Bit[3]是否为 1(通过发送0x71可以获取一个字节的状态字)，
// 如果不为1，要发送0xBE命令(初始化)，此命令参数有两个字节， 第一个字节为0x08，第二个字节为0x00。
uint32_t AHT20_Calibrate(void)
{
    uint32_t retval = 0;
    uint8_t buffer[AHT20_STATUS_RESPONSE_MAX] = { AHT20_STATUS };
    memset(&buffer, 0x0, sizeof(buffer));

    retval = AHT20_Status();
    if (retval != IOT_SUCCESS) {
        return retval;
    }

    retval = AHT20_Read(buffer, sizeof(buffer));
    if (retval != IOT_SUCCESS) {
        return retval;
    }

    if (AHT20_STATUS_BUSY(buffer[0]) || !AHT20_STATUS_CALI(buffer[0])) {
        retval = AHT20_Reset();
        if (retval != IOT_SUCCESS) {
            return retval;
        }
        usleep(AHT20_WAIT_TIME);
        retval = AHT20_Initcmd();
        usleep(AHT20_WAIT_TIME);
        return retval;
    }
    return IOT_SUCCESS;
}


// 接收测量结果，拼接转换为标准值
uint32_t AHT20_GetMeasureResult(float* temp, float* humi)
{
    uint32_t retval = 0, i = 0;
    if (temp == NULL || humi == NULL) {
        return IOT_FAILURE;
    }

    uint8_t buffer[AHT20_STATUS_RESPONSE_MAX] = { 0 };
    memset(&buffer, 0x0, sizeof(buffer));
    retval = AHT20_Read(buffer, sizeof(buffer));  // recv status command result
    if (retval != IOT_SUCCESS) {
        return retval;
    }

    for (i = 0; AHT20_STATUS_BUSY(buffer[0]) && i < AHT20_MAX_RETRY; i++) {
        // printf("AHT20 device busy, retry %d/%d!\r\n", i, AHT20_MAX_RETRY);
        usleep(AHT20_WAIT_TIME);
        retval = AHT20_Read(buffer, sizeof(buffer));  // recv status command result
        if (retval != IOT_SUCCESS) {
            return retval;
        }
    }
    if (i >= AHT20_MAX_RETRY) {
        printf("AHT20 device always busy!\r\n");
        return IOT_FAILURE;
    }

    uint32_t humiRaw = buffer[1];
    humiRaw = (humiRaw << 8) | buffer[2];
    humiRaw = (humiRaw << 4) | ((buffer[3] & 0xF0) >> 4);
    *humi = humiRaw / (float)AHT20_RESLUTION * 100;

    uint32_t tempRaw = buffer[3] & 0x0F;
    tempRaw = (tempRaw << 8) | buffer[4];
    tempRaw = (tempRaw << 8) | buffer[5];
    *temp = tempRaw / (float)AHT20_RESLUTION * 200 - 50;
    // printf("humi = %05X, %f, temp= %05X, %f\r\n", humiRaw, *humi, tempRaw, *temp);
    return IOT_SUCCESS;
}
